﻿#ifndef _ASF_INFO_H_
#define _ASF_INFO_H_
#include<stdint.h>

struct object_header_t {
	uint8_t guid[16];
	uint64_t size;
};
typedef union {
	uint32_t value;
	struct {
		uint32_t broadcast     : 1;
		uint32_t seekable      : 1;
		uint32_t usepktmplate  : 1; 
		uint32_t live          : 1;
		uint32_t reliable      : 1;
		uint32_t recordable    : 1;
		uint32_t reserved      : 26;
	};
}fpobj_flags_t;

#pragma pack(push)
#pragma pack(1)
struct asf_file_properties_object_t {
	struct object_header_t objheader;
	uint8_t file_id[16];           					/* this value shall be regenerated every time the file is modified   */
	/* It's identical to the value of file_id of DataObject              */
	uint64_t file_size;             					/* whole asf file size, it's invalid if broadcast_flag = 1           */
	uint64_t create_time;		  					/* unit: 100ns, from 1601-01-01, UTC time, invalid if broadcast = 1  */
	uint64_t datapacket_counts;     					/* the number of DataPacket entries within the DataObject,invlaid if broadcast=1*/ 
	uint64_t play_duration;         					/* unit: 100ns,0.1us, it's invalid if broadcast = 1                  */
	uint64_t send_duration;         					/* unit: 100ns,0.1us, it's invalid if broadcast = 1                  */
	uint64_t preroll;               					/* unit: ms*/
	fpobj_flags_t flags;	
	uint32_t min_datapacket_size;
	uint32_t max_datapacket_size;
	uint32_t max_bitrate;            				/* unit: bit/sec */
};

struct asf_header_extension_object_t {
	struct object_header_t objheader;
	uint8_t reserved_field1[16];               		/* This value shall be set to ASF_Reserved_1  */
	uint16_t reserved_field2;              			/* This value should be set to 6  */
	uint32_t datasize;
};                                  
struct asf_language_list_object_t {
	struct object_header_t objheader;
	uint16_t langnums;   
	uint8_t langlen;
	uint8_t langbuf[12];
};

struct asf_data_object_t {
	struct object_header_t objheader;	   			/* if broadcast flag is 0,objheader.size field may be 0        */
	uint8_t file_id[16];                      		/* same as  file_id of FilePropertiesObject of HeaderObject */
	uint64_t total_datapacket;                		/* invalid if broadcast flag = 1 */
	uint16_t reserved;                         		/* should be set to 0x0101 */  
};

struct asf_padding_object_t {
	struct object_header_t 	objheader;
};

struct asf_content_description_base_t 
{
	struct object_header_t objheader;
	uint16_t title_len;     							/* size, in bytes */ 
	uint16_t author_len;
	uint16_t copyright_len;
	uint16_t description_len;
	uint16_t rating_len;
};

struct asf_content_description_object_t 
{
	struct object_header_t objheader;
	uint16_t title_len;     							/* size, in bytes */ 
	uint16_t author_len;
	uint16_t copyright_len;
	uint16_t description_len;
	uint16_t rating_len;
	uint8_t *title_pbuf;
	uint8_t *author_pbuf;
	uint8_t *copyright_pbuf;
	uint8_t *description_pbuf;
	uint8_t *rating_pbuf;
};
struct asf_header_object_t 
{
	struct object_header_t objheader;
	uint32_t subobj_nums;      						/* How many sub objects in header-object ? */  
	uint8_t align;            						/* Must be: 0x01 */
	uint8_t architecture;     						/* Must be: 0x02 */  
};

struct asf_video_stream_properties_object_t 
{
	struct object_header_t objheader;	           
	uint8_t stream_type_id[16];		        		/* Audio,Video,and so on */	
	uint8_t err_correction_type_id[16];	 			/* For streams other than audio,this value be set to ASF_No_Error_Correction*/
	/* For audio streams,be this value be set to ASF_Audio_Spread  */	
	uint64_t time_offset;                      		/* Typical, is 0  */
	uint32_t type_specified_datalen;           		/* Type-Specific Data Length */
	uint32_t err_correction_datalen;      
	uint16_t flags;                            		/* LSB(0...6) is Stream Number, MSB(bit15) is Entrypted Content Flag */         
	uint32_t reserved;                         		/* Should set to 0 */
	uint32_t encoded_image_width;       				/* 352  */  /* From here, is type_specified_datalen */
	uint32_t encoded_image_height;      				/* 288  */
	uint8_t reserved_flags;                  		/* shall be set to 2 */
	uint16_t format_datasize;                		/* Bitmap size, for example,76 bytes, size not include this item */
	uint32_t bisize;                           		/* BITMAPINFOHEADER, For example, 76 bytes */
	uint32_t width;                            		/* 352  */
	uint32_t height;                           		/* 288  */  
	uint16_t planes;                           		/* 1     */
	uint16_t bitsofpixels;                     		/* 24    */
	uint32_t compress_id;                      		/* For Example: H264 */
	uint32_t image_size;                       		/* width * height * (bitsofpixels/8), for example,352x288x3=230400 */
	uint32_t x_each_meter;                    	 	/* 0x00000000 */
	uint32_t y_each_meter;                     		/* 0x00000000 */
	uint32_t color_used;                       		/* 0x00000000 */
	uint32_t color_important;                  		/* 0x00000000 */
//	uint32_t my_pos;											   
//	uint8_t *codec_specific_data_pbuf;        		/* this length = format_datasize - 40; */ /* To h264, here is SPS and PPS         */ 	
};

struct asf_audio_stream_properties_object_t {
	struct object_header_t objheader;	           
	uint8_t stream_type_id[16];		    			/* Audio,Video,and so on */	
	uint8_t err_correction_type_id[16];				/* For streams other than audio,this value be set to ASF_No_Error_Correction*/
	/* For audio streams,be this value be set to ASF_Audio_Spread  */	
	uint64_t time_offset;                  			/* Typical, be set to 0  */
	uint32_t type_specified_datalen;       			/* Type-Specific Data Length,30 bytes */
	uint32_t err_correction_datalen;      		 	/* Error correction data length */     
	uint16_t flags;                        			/* LSB(0...6) is Stream Number, MSB(bit15) is Entrypted Content Flag */         
	uint32_t reserved;			         			/* Should set to 0 */
	/* Type-Specific Data, 30 bytes varies length */	
	uint16_t format_tag;                   			/* Codec ID/Format Tag, For example: 353(WMA2), 0x0045(ADPCM G.726)*/
	uint16_t channels;                     			/* mono: 1; stereo: 2 */ 
	uint32_t sample_per_sec;               			/* 8000 Hz       */
	uint32_t bytes_per_sec;                			/* 16000 Bytes   */
	uint16_t block_align;   
	uint16_t bits_per_sample;              			/* 2 bits */
	uint16_t extra_datasize;
	//uint32_t my_pos;
	//uint8_t *err_correction_data_pbuf;    			/* Length is err_correction_datalen above */
};

struct codec_attr_t 
{
	uint16_t type;                         			/* 0x0001:Video codec; 0x0002: Audio codec; 0xFFFF,unknown codec */
	uint16_t name_len;                  				/* unicode length !!! */   
	uint8_t *name_buf;                				/* unicode wildchar string, length = namelen */ 
	uint16_t descript_len;               			/* unicode length !!!,can set to 0 */
	uint8_t *descript_buf;    
	uint16_t infor_len;                    			/* For Example, 04 00 48 32 36 34, It's H264 */
	uint8_t *infor_buf;
};

struct asf_codec_list_onject_t  
{			
	struct object_header_t objheader;
	uint8_t reserved_field[16];             			/* Should be set to ASF_Reserved_2 */  
	uint32_t codec_nums;                				/* 2 */
	struct codec_attr_t codec[2];
};


//struct gps_asfsave_t padding_buffer[MAIN_CHN_NUMS][PADDING_MAX_GPS_SECS]; 	// 最大保存400秒的GPS信息,具体多少有效由ASF视频时间决定
//struct gps_asfsave_t hist_paddingbuf[PADDING_MAX_GPS_SECS];  				//用于历史记录回放

typedef struct {
	uint32_t packet_number;    						/* PacketNumber of ASF DataPacket with the closest past KEY-FRAME */
	uint16_t packet_count;
} indexentry_t;

struct asf_simple_index_object_t {
	struct object_header_t objheader;	 
	uint8_t                 file_id[16];             /* identical to FileID of DataObject and HeaderObject */
	uint64_t                index_entrytime_interval;/* Specifies the time interval between each in 100ns units */
	/* The most Common value is 10000000, 1 second  */
	uint32_t                max_packet_count;        /* Specifies the maximum PacketCount value of all Index Entry */
	uint32_t                index_entry_count;       /* Specifies the number of Index Entries */               
};
struct curr_datapacket_status_t {
	uint32_t offset; 
	int32_t payload_nums;
	uint32_t sendtime;   							//第一个Payload的Presentation Time减去Preroll时间
	uint16_t duration;   							//最后一个Payload的PresentionTime减去第一个Payload的Presentation Time
						 							//如果是单Playload，则Duration=0x0000
	int32_t first_payload_flag;  					//是否本DataPacket中已经包含了第一个Payload
	uint32_t first_presentation; 					//第一个Payload的Presentation Time,记下来用于计算Duration
	uint32_t curr_presentation;  					//最新的一个Payload的Presentation time	
};
struct write_datapacket_parameter_t {
	uint32_t curr_packet_no;    
	uint32_t send_time;
	uint16_t duration_time;
	uint8_t curr_media_object;
	uint32_t offset_of_media_object;
	uint32_t media_object_size;
	uint32_t presentation_time;	
	uint16_t keyframe_flag;
};
typedef union {
	uint8_t value;
	struct {
		uint8_t numbers       : 6;
		uint8_t length_type   : 2;
	};	
}PayloadFlag_t;

typedef union {                                 	/* Length Type Flags of Payload Parsing information */ 
	uint8_t value;                                	/* For example: 0x01 */
	struct {
		uint8_t multi_payloads_present 	: 1;   		/* if set,DataPacket contains multiple payloads */
		uint8_t sequence_type          	: 2;   		/* Sequence field, 00: non-exist; 01: coded using a BYTE; 10: using a WORD; 11: using a DWORD */ 
		uint8_t padding_length_type    	: 2;   		/* Padding field,00:non-exist; 01:coded using a Byte; 10: using a WORD; 11: using a DWORD */ 
		uint8_t packet_length_type     	: 2;   		/* PacketLength filed, 00:non-exist; 01: coded using a Byte; 10: a WORD; 11: a DWORD */
		uint8_t err_correction_present 	: 1;   	       
	};	 
}LengthTypeFlags_t;

typedef union {                                     /* Property Flags of Payload parsing information */
	uint8_t value;                                	/* For Example, 0x5D */
	struct {
		uint8_t replicated_data_len_type : 2;   		/* ReplicatedDataLength field, 00:not-exist;01:coded using a Byte;10:a WORD; 11: a DWORD,shall be set to 01 */
		uint8_t offset_mediaobj_len_type : 2;   		/* Offset Into Media Object Length, same as above, shall be set to 11*/
		uint8_t mediaobj_number_len_type : 2;   		/* Media Object Number Length, same as above,shall be set to 01 */
		uint8_t stream_number_len_type   : 2;   		/* Stream Number Length Type, same as above,shall be set to 01  */ 
	};
}PropertyFlags_t;

struct payload_parsing_information_t {    		/* Payload Parsing information struct */
	LengthTypeFlags_t lentype_flag;              	/* 0x01 */
	PropertyFlags_t property_flag;             		/* 0x5D */
	uint32_t packet_length;           				/* Packet Length field, Size is 0/8(BYTE)/16(WORD)/32(DWORD), it's 0 bit */	
	uint32_t sequence;	            				/* Sequence field, same as above,reserved for future use*/
	uint32_t padding_length;          				/* Padding Length field, same as above */
	uint32_t send_time;               				/* Specifies the send time of the DataPacket, unit: ms,For Example, 0ms */
	uint16_t duration;                				/* Specifies the duration of the DataPacket,unit: ms, For Example, 100ms */  
};

typedef union {
	uint8_t value;
	struct {
		uint8_t number 		: 7;
		uint8_t key_frame   	: 1;
	};
}StreamNumber_t;
//这个注意,replicated_data[2],在从ASF文件读取解析时,replicated_data[1]表示为 FirstWORD, replicated_data[0]表示为Second WORD
struct single_payload_t {
	StreamNumber_t stream_number;          	   		/* MSB is key_frame, 0~7: which stream? Video or Audio */
	uint8_t media_object_number;    					/* Which MediaObject this payload belong to?  */
	uint32_t offset_mediaobj;          				/* Offset in the MediaObject this payload belongs to */
	uint8_t replicated_data_len;    					/* 08 */ 
	uint32_t mediaobject_size;
	uint32_t present_time;
													/* Second DWORD: the presentation time of MediaObject that this payload belongs to, ms */					
//	uint8_t payload_pbuf[0];          					/* Indeed video/audio stream encoded data,length can be caculated */ 
};  		   					/* packet has only a payload */
typedef union {
	uint8_t value;
	struct {
		uint8_t data_length           : 4;          	/* valid only while lentype is 00,should set to 0010    */
		uint8_t opaque_data_present   : 1;    		/* should set to 0 */
		uint8_t length_type           : 2;          	/* should set to 00 */
		uint8_t present_flag          : 1;          	/* if be set to 1, DataPacket start with error correction information */
						                        	/* set to 0, DataPacket start with Payload parsing information        */ 	
	};
} ErrorCorrectionFlags_t;

struct error_correction_data_t {
	ErrorCorrectionFlags_t flag;     				/* 0x82    */
	uint16_t data;	                    			/* 0x0000 */
};  
#pragma pack(pop)

struct stream_info_t
{
	uint16_t vWidth;
	uint16_t vHeight;
	uint32_t bitRate;
};

struct asfvideo_time_t {
	int32_t hour;
	int32_t minute;
	int32_t second;
	int32_t msnums;
};

static const uint8_t simple_index_object_id[16] = {0x90,0x08,0x00,0x33,0xB1,0xE5,0xCF,0x11,0x89,0xF4,0x00,0xA0,0xC9,0x03,0x49,0xCB};
static const uint8_t data_object_id[16] = {0x36,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C};
static const uint8_t header_object_id[16] = {0x30,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C};
static const uint8_t file_properties_object_id[16] = {0xA1,0xDC,0xAB,0x8C,0x47,0xA9,0xCF,0x11,0x8E,0xE4,0x00,0xC0,0x0C,0x20,0x53,0x65};
static const uint8_t language_list_object_id[16] = {0xA9,0x46,0x43,0x7C,0xE0,0xEF,0xFC,0x4B,0xB2,0x29,0x39,0x3E,0xDE,0x41,0x5C,0x85};
static const uint8_t lang_name[12] = {0x7a,0x00,0x68,0x00,0x2d,0x00,0x63,0x00,0x6e,0x00,0x00,0x00};

static const uint8_t padding_object_id[16] = {0x74,0xD4,0x06,0x18,0xDF,0xCA,0x09,0x45,0xA4,0xBA,0x9A,0xAB,0xCB,0x96,0xAA,0xE8};
static const uint8_t header_extension_object_id[16] = {0xB5,0x03,0xBF,0x5F,0x2E,0xA9,0xCF,0x11,0x8E,0xE3,0x00,0xC0,0x0C,0x20,0x53,0x65};
static const uint8_t asf_reserved_1_id[16] = {0x11,0xD2,0xD3,0xAB,0xBA,0xA9,0xCF,0x11,0x8E,0xE6,0x00,0xC0,0x0C,0x20,0x53,0x65};
static const uint8_t content_description_onject_id[16] = {0x33,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C};
static const uint8_t stream_properties_object_id[16] = {0x91,0x07,0xDC,0xB7,0xB7,0xA9,0xCF,0x11,0x8E,0xE6,0x00,0xC0,0x0C,0x20,0x53,0x65};
static const uint8_t video_stream_object_id[16] = {0xC0,0xEF,0x19,0xBC,0x4D,0x5B,0xCF,0x11,0xA8,0xFD,0x00,0x80,0x5F,0x5C,0x44,0x2B};
static const uint8_t video_conceal_none_id[16] = {0x00,0x57,0xFB,0x20,0x55,0x5B,0xCF,0x11,0xA8,0xFD,0x00,0x80,0x5F,0x5C,0x44,0x2B};
static const uint8_t audio_stream_object_id[16] = {0x40,0x9E,0x69,0xF8,0x4D,0x5B,0xCF,0x11,0xA8,0xFD,0x00,0x80,0x5F,0x5C,0x44,0x2B};
static const uint8_t audio_conceal_spread_id[16] = {0x50,0xCD,0xC3,0xBF,0x8F,0x61,0xCF,0x11,0x8B,0xB2,0x00,0xAA,0x00,0xB4,0xE2,0x20};
static const uint8_t codec_list_object_id[16] = {0x40,0x52,0xD1,0x86,0x1D,0x31,0xD0,0x11,0xA3,0xA4,0x00,0xA0,0xC9,0x03,0x48,0xF6};
static const uint8_t asf_reserved_2_id[16] = {0x41,0x52,0xD1,0x86,0x1D,0x31,0xD0,0x11,0xA3,0xA4,0x00,0xA0,0xC9,0x03,0x48,0xF6};

const int OBJECTID_LEN			= 12;
const int VIDEO_STREAM_NUMBER	= 1;
const int AUDIO_STREAM_NUMBER	= 2;
const int PADDING_MAX_GPS_SECS	= 400;      			//ASF 头扩展对象中的Padding对象所占空间
const int ENCODER_G726          = 0x0045; 
const int PREROLL_TIME          = 3100;          		//3100 ms
const uint16_t g726_frame_interval_time = 40;  		//40ms
const int ASF_FILE_INFO_LEN     = SIZE_8KB;				//与硬盘扇区整数倍对齐
const int ASF_DATA_OBJ_LEN      =sizeof(struct asf_data_object_t);
const int ASF_OBJ_HEAD_LEN      =sizeof(struct object_header_t);
const int ASF_FILEHEAD_OBJ_LEN  =sizeof(struct asf_header_object_t);
const int ASF_MAX_INDEX_LEN     =SIZE_32KB;
#endif //_ASF_INFO_H_